﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ACLibs.DBHelper
{
    /// <summary>
    /// ProviderFactory工厂类
    /// </summary>
    public class DBProvider
    {
        private static Dictionary<DBProviderType, string> providerInvariantNames = new Dictionary<DBProviderType, string>();
        private static Dictionary<DBProviderType, DbProviderFactory> providerFactoies = new Dictionary<DBProviderType, DbProviderFactory>(20);
        static DBProvider()
        {
            if (providerInvariantNames.Count == 0)
            {
                //加载已知的数据库访问类的程序集
                providerInvariantNames.Add(DBProviderType.SqlServer, "System.Data.SqlClient");
                providerInvariantNames.Add(DBProviderType.OleDb, "System.Data.OleDb");
                providerInvariantNames.Add(DBProviderType.ODBC, "System.Data.ODBC");
                providerInvariantNames.Add(DBProviderType.Oracle, "Oracle.DataAccess.Client");
                providerInvariantNames.Add(DBProviderType.MySql, "MySql.Data.MySqlClient");
                providerInvariantNames.Add(DBProviderType.SQLite, "System.Data.SQLite");
                providerInvariantNames.Add(DBProviderType.Firebird, "FirebirdSql.Data.Firebird");
                providerInvariantNames.Add(DBProviderType.PostgreSql, "Npgsql");
                providerInvariantNames.Add(DBProviderType.DB2, "IBM.Data.DB2.iSeries");
                providerInvariantNames.Add(DBProviderType.Informix, "IBM.Data.Informix");
                providerInvariantNames.Add(DBProviderType.SqlServerCe, "System.Data.SqlServerCe");
            }

        }

        /// <summary>
        /// 获取指定数据库类型对应的程序集名称
        /// </summary>
        /// <param name="providerType">数据库类型枚举</param>
        /// <returns></returns>
        public static string GetProviderInvariantName(DBProviderType providerType)
        {
            return providerInvariantNames[providerType];
        }

        /// <summary>
        /// 获取指定提供程序的枚举名称
        /// </summary>
        /// <param name="providerName">程序集名称</param>
        /// <returns></returns>
        public static DBProviderType GetProviderType(string providerName)
        {
            DBProviderType dbptype;

            try
            {
                dbptype = providerInvariantNames.First(t => t.Value == providerName).Key;
                return dbptype;

            }
            catch
            {
                throw new Exception("指不到配置文件中连接字符串中providerName对应的名称定义1");
            }

        }

        /// <summary>
        /// 获取指定类型的数据库对应的DbProviderFactory
        /// </summary>
        /// <param name="providerType">数据库类型枚举</param>
        /// <returns></returns>
        public static DbProviderFactory GetDbProviderFactory(DBProviderType providerType)
        {
            //如果还没有加载，则加载该DbProviderFactory
            if (!providerFactoies.ContainsKey(providerType))
            {
                providerFactoies.Add(providerType, ImportDbProviderFactory(providerType));
            }
            return providerFactoies[providerType];
        }
        /// <summary>
        /// 加载指定数据库类型的DbProviderFactory
        /// </summary>
        /// <param name="providerType">数据库类型枚举</param>
        /// <returns></returns>
        private static DbProviderFactory ImportDbProviderFactory(DBProviderType providerType)
        {
            string providerName = providerInvariantNames[providerType];
            DbProviderFactory factory = null;
            try
            {
                //从全局程序集中查找
                factory = DbProviderFactories.GetFactory(providerName);
            }
            catch (ArgumentException)
            {
                factory = null;
            }
            return factory;
        }

    }

    /// <summary>
    /// 数据库类型枚举
    /// </summary>
    public enum DBProviderType : byte
    {
        SqlServer,
        MySql,
        SQLite,
        Oracle,
        ODBC,
        OleDb,
        Firebird,
        PostgreSql,
        DB2,
        Informix,
        SqlServerCe,
        Access
    }

}
